package com.awx.server.registration;

import org.jdom.Element;
import org.jdom.Namespace;

import com.awx.server.service.AwxService;
import com.awx.server.service.AwxServiceImpl;

/**
 * Information of a service to be register to the client and server Spring Ioc xml
 *
 * @author Matias Leone
 */
public class AwxServiceInfo {

	//Spring classes
	private final static String SPRING_HTTP_INVOKER_CLASS_NAME = "org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter";
	private final static String SPRING_HTTP_PROXY_FACTORY_CLASS_NAME = "org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean";
	public static final String SPRING_NAMESPACE = "http://www.springframework.org/schema/beans";

	//tags
	public final static String BEAN_TAG_NAME = "bean";
	private final static String ID_TAG_NAME = "id";
	private final static String CLASS_TAG_NAME = "class";
	private final static String PROPERTY_TAG_NAME = "property";
	private final static String NAME_TAG_NAME = "name";
	private final static String VALUE_TAG_NAME = "value";
	private final static String REF_TAG_NAME = "ref";

	//Default values
	private final static String SERVICE_URL_VALUE = "serviceUrl";
	private final static String SERVICE_VALUE = "service";
	private final static String SERVICE_INTERFACE_VALUE = "serviceInterface";

	private Class<? extends AwxService> serviceInterface;
	Class<? extends AwxServiceImpl> serviceImpl;
	private String implClassName;
	private String interfaceClassName;
	private String serviceName;
	private String serviceUrl;


	/**
	 * Create the information
	 * @param serviceName
	 * @param serviceInterface
	 * @param serviceImpl
	 * @param baseUrl
	 */
	public AwxServiceInfo( String serviceName, Class<? extends AwxService> serviceInterface, Class<? extends AwxServiceImpl> serviceImpl, String baseUrl ) {
		this.serviceName = serviceName;
		this.serviceInterface = serviceInterface;
		this.serviceImpl = serviceImpl;

		//calculate names and url
		this.serviceUrl = baseUrl + serviceName;
		this.implClassName = this.serviceImpl.getName();
		this.interfaceClassName = this.serviceInterface.getName();
	}

	/**
	 * Build both beans required in the server xml
	 * @return
	 */
	public Element[] buildBeansServer() {
		Element[] beans = new Element[2];

		//simple bean
		Element simpleBeanEl = new Element( BEAN_TAG_NAME );
		beans[ 0 ] = simpleBeanEl;
		simpleBeanEl.setAttribute( ID_TAG_NAME, this.serviceName );
		simpleBeanEl.setAttribute( CLASS_TAG_NAME, this.implClassName );
		simpleBeanEl.setNamespace( Namespace.getNamespace( SPRING_NAMESPACE ) );

		//Http bean
		Element httpBeanEl = new Element( BEAN_TAG_NAME );
		beans[ 1 ] = httpBeanEl;
		httpBeanEl.setAttribute( NAME_TAG_NAME, "/" + this.serviceName );
		httpBeanEl.setAttribute( CLASS_TAG_NAME, SPRING_HTTP_INVOKER_CLASS_NAME);
		httpBeanEl.setNamespace( Namespace.getNamespace( SPRING_NAMESPACE ) );

		//prop service
		Element propServiceEl = new Element( PROPERTY_TAG_NAME );
		propServiceEl.setAttribute( NAME_TAG_NAME,  SERVICE_VALUE );
		propServiceEl.setAttribute( REF_TAG_NAME,  this.serviceName );
		propServiceEl.setNamespace( Namespace.getNamespace( SPRING_NAMESPACE ) );
		httpBeanEl.addContent( propServiceEl );

		//prop serviceInterface
		Element propServiceIntEl = new Element( PROPERTY_TAG_NAME );
		propServiceIntEl.setAttribute( NAME_TAG_NAME,  SERVICE_INTERFACE_VALUE );
		propServiceIntEl.setAttribute( VALUE_TAG_NAME,  this.interfaceClassName );
		propServiceIntEl.setNamespace( Namespace.getNamespace( SPRING_NAMESPACE ) );
		httpBeanEl.addContent( propServiceIntEl );

		return beans;
	}

	/**
	 * Build the bean required in the client xml
	 * @return
	 */
	public Element buildBeanClient() {
		//bean
		Element bean = new Element( BEAN_TAG_NAME );
		bean.setAttribute( ID_TAG_NAME, this.serviceName );
		bean.setAttribute( CLASS_TAG_NAME, SPRING_HTTP_PROXY_FACTORY_CLASS_NAME );
		bean.setNamespace( Namespace.getNamespace( SPRING_NAMESPACE ) );

		//prop serviceUrl
		Element propServiceUrlEl = new Element( PROPERTY_TAG_NAME );
		propServiceUrlEl.setAttribute( NAME_TAG_NAME, SERVICE_URL_VALUE );
		propServiceUrlEl.setAttribute( VALUE_TAG_NAME, this.serviceUrl );
		propServiceUrlEl.setNamespace( Namespace.getNamespace( SPRING_NAMESPACE ) );
		bean.addContent( propServiceUrlEl );

		//prop serviceInterface
		Element propServiceIntEl = new Element( PROPERTY_TAG_NAME );
		propServiceIntEl.setAttribute( NAME_TAG_NAME, SERVICE_INTERFACE_VALUE );
		propServiceIntEl.setAttribute( VALUE_TAG_NAME, this.interfaceClassName );
		propServiceIntEl.setNamespace( Namespace.getNamespace( SPRING_NAMESPACE ) );
		bean.addContent( propServiceIntEl );

		return bean;
	}

}
